#ifndef MEASURE_DV_DESTINATION_H
#define MEASURE_DV_DESTINATION_H

#include "dvdest.h"
#include "dvlog.h"

class MeasureDVDestination : public IDVDestination
{
public:
	MeasureDVDestination(int32_t log_period = 300)
	{
		this->log_period = log_period;
		loss = 0;
		packets = 0;
		bytes_recved = 0;
		last_seq = 0;
		first_packet = true;
		start_time = DateTime::Now().GetTickCount();
	}
protected:
	virtual bool DealPacket(char* packet, int length, const IPEndPoint& ep)
	{
		if(length < 4)
		{
			return false;
		}
		u_int16_t seq = ntohs(*(u_int16_t*)(packet + 2));
		++packets;
		bytes_recved += length;
		if(first_packet)
		{
			first_packet =false;
		}
		else
		{
			if(seq < 1000 && last_seq > 60000)
			{
				loss += (int)seq + 65536 - last_seq - 1;
			}
			else if(seq > last_seq)
			{
				loss += seq - last_seq - 1;
			}
		}
		last_seq = seq;
		int64_t now = DateTime::Now().GetTickCount();
		if(now - start_time > log_period * 1000000LL)
		{
			DateTime st(start_time);
			st.ToLocalTime();
			dvlog.lock();
			dvlog << "measure " << (now - start_time) / 1000 << "ms, from " << st << ", 1" << endl;
			dvlog << packets << " " << bytes_recved * 8.0 / (now - start_time) << "Mbps " << loss * 100.0 / (loss + packets) << "%" << endl;
			dvlog.unlock();
			start_time = now;
			packets = 0;
			bytes_recved = 0;
			loss = 0;
		}
		return true;
	}
private:
	int32_t packets;
	int64_t bytes_recved;
	int32_t loss;
	u_int16_t last_seq;
	bool first_packet;
	int64_t start_time;
	int32_t log_period;
};

#endif // !defined(MEASURE_DV_DESTINATION_H)

